

// 数字转换为16进制字符取两位
function numToHex(a: number, k: number = 2) {
  for (var b = a.toString(16); b.length < k;) b = "0" + b;
  return b.toUpperCase()
}

// 创建一个HSV颜色值
export class HSVColor {
  H: number = 0;
  S: number = 0;
  V: number = 0;
  constructor(h: number, s: number, v: number) {
    this.set(h, s, v);
  }
  set(h: number, s: number, v: number) {
    this.H = h;
    this.S = s;
    this.V = v
  };
  copy() {
    return new HSVColor(this.H, this.S, this.V)
  };
}


export class RGB {
  R: number = 0;
  G: number = 0;
  B: number = 0;
  Name: Array<string> | undefined = [];

  constructor(r: number, g: number, b: number) {
    this.set(r, g, b);
  }
  set(r: number, g: number, b: number) {
    this.R = Math.round(r);
    this.G = Math.round(g);
    this.B = Math.round(b)
  };
  copy() {
    return new RGB(this.R, this.G, this.B)
  };
  toWebCol() {
    this.R = Math.round(this.R / 51) * 51;
    this.G = Math.round(this.G / 51) * 51;
    this.B = Math.round(this.B / 51) * 51
  };
  // toPantone() {
  //   var a = c.Pantone.search(this);
  //   if (a) this.R = a.RGB.R, this.G = a.RGB.G, this.B = a.RGB.B, this.Name = [a.Name]
  // };
  // toRAL() {
  //   var a = c.RAL.search(this);
  //   if (a) this.R = a.RGB.R, this.G = a.RGB.G, this.B = a.RGB.B, this.Name = [a.Name, a.Name2]
  // };
  // toOpaltone() {
  //   var a = c.Opaltone.search(this);
  //   if (a) this.R = a.RGB.R, this.G = a.RGB.G, this.B = a.RGB.B, this.Name = [a.Name]
  // };
  getCSS() {
    return "rgb(" + this.R + "," + this.G + "," + this.B + ")"
  };
  getHex() {
    return numToHex(this.R) + numToHex(this.G) + numToHex(this.B)
  };
  getName() {
    return this.Name || []
  };
}


export const COLOR_STAND = {
  R: {
    RGB: new RGB(255, 0, 0),
    HSV: new HSVColor(0, 1, 1)
  },
  RG: {
    RGB: new RGB(255, 255, 0),
    HSV: new HSVColor(120, 1, 1)
  },
  G: {
    RGB: new RGB(0, 255, 0),
    HSV: new HSVColor(180, 1, 0.8)
  },
  GB: {
    RGB: new RGB(0, 255, 255),
    HSV: new HSVColor(210, 1, 0.6)
  },
  B: {
    RGB: new RGB(0, 0, 255),
    HSV: new HSVColor(255, 0.85, 0.7)
  },
  BR: {
    RGB: new RGB(255, 0, 255),
    HSV: new HSVColor(315, 1, 0.65)
  }
};

function f(a:number, k:number) {
  k - a > 180 ? a += 360 : a - k > 180 && (k += 360);
  return k - a
}
function g(a: number, k: number, b: number) {
  return b == -1 ? a : a + (k - a) / (1 + b)
}
function m(a: number, k: number, b: number) {
  return b == -1 ? k : k + (a - k) / (1 + b)
}

export interface ModelFormat {
  getH: Function,
  getD: Function,
  minD: number,
  maxD: number
}

// 六种UI颜色模式: [单色, 单色互补, 三角色, 四方色, 相似色, 相似互补]
export const UI_MODEL = {
  m1: {
    getH: function () {
      return {}
    },
    minD: 5,
    maxD: 90,
    getD: function () {
      return 0
    }
  },
  m2: {
    getH: function (a:number) {
      return {
        C: (a + 180) % 360
      }
    },
    minD: 5,
    maxD: 90,
    getD: function () {
      return 0
    }
  },
  m3: {
    getH: function (a:number, b:number) {
      return {
        S1: (a + b + 180) % 360,
        S2: (a - b + 540) % 360
      }
    },
    minD: 5,
    maxD: 90,
    getD: function (a:number, b:number) {
      var c = Math.abs(f(a + 180, b));
      if (c < this.minD) c = this.minD;
      if (c > this.maxD) c = this.maxD;
      return c
    }
  },
  m4: {
    getH: function (a:number, b:number) {
      return {
        C: (a + 180) % 360,
        S1: (a + b + 360) % 360,
        S2: (a + b + 540) % 360
      }
    },
    minD: 5,
    maxD: 90,
    getD: function (a:number, b:number) {
      var c, d, e;
      c = f(a, b);
      e = Math.abs(c);
      d = f(a + 180, b);
      Math.abs(d) < e && (c = d);
      e < this.minD && (c = c >= 0 ? this.minD : -this.minD);
      e > this.maxD && (c = c >= 0 ? this.maxD : -this.maxD);
      return c
    }
  },
  m5: {
    getH: function (a:number, b:number) {
      return {
        S1: (a + b) % 360,
        S2: (a - b + 360) % 360
      }
    },
    minD: 5,
    maxD: 90,
    getD: function (a:number, b:number) {
      var c = Math.abs(f(a, b));
      if (c < this.minD) c = this.minD;
      if (c > this.maxD) c = this.maxD;
      return c
    }
  },
  m6: {
    getH: function (a:number, b:number) {
      return {
        C: (a + 180) % 360,
        S1: (a + b) % 360,
        S2: (a - b + 360) % 360
      }
    },
    minD: 5,
    maxD: 90,
    getD: function (a:number, b:number) {
      var c = Math.abs(f(a, b));
      if (c < this.minD) c = this.minD;
      if (c > this.maxD) c = this.maxD;
      return c
    }
  }
};



// 用于设置获取图像的对比度
// 自始至终初始化一次初始化get 0.5, 0.5
// ContrastModel 赋了一个初始值
export const themeManager = {
  shadow: [{
    dS: -0.5,
    dV: -0.5
  }, {
    dS: 1,
    dV: -0.7
  }],
  light: [{
    dS: -0.5,
    dV: 1
  }, {
    dS: -0.9,
    dV: 1
  }],
  get: function (a:number, b:number) {
    var c = [];
    c.push({
      dS: this.shadow[0].dS * a,
      dV: this.shadow[0].dV * a
    });
    c.push({
      dS: this.shadow[1].dS * a,
      dV: this.shadow[1].dV * a
    });
    c.push({
      dS: this.light[0].dS * b,
      dV: this.light[0].dV * b
    });
    c.push({
      dS: this.light[1].dS * b,
      dV: this.light[1].dV * b
    });
    return c
  }
};

interface ColorAxisFormat {
  a: any,
  b: any,
  f: any,
  fi: any,
  g: Function,
  orderRGB: Function
}

// 解析当前选中的色调和对应的色值
export const ColorAnalysis = {
  getArc: function (a: number) {
    if (a < 120) return this.RRG;
    if (a < 180) return this.RGG;
    if (a < 210) return this.GGB;
    if (a < 255) return this.GBB;
    if (a < 315) return this.BBR;
    return this.BRR
  },
  RRG: {
    a: COLOR_STAND.R,
    b: COLOR_STAND.RG,
    f: function (a: number) {
      if (a == 0) return -1;
      return Math.tan((120 - a) / 120 * Math.PI / 2) * 0.5
    },
    fi: function (a: number) {
      if (a == -1) return 0;
      return 120 - Math.atan(a / 0.5) * 120 / Math.PI * 2
    },
    g: g,
    orderRGB: function (a: number, b: number, c: number) {
      return new RGB(a, b, c)
    }
  },
  RGG: {
    a: COLOR_STAND.RG,
    b: COLOR_STAND.G,
    f: function (a: number) {
      if (a == 180) return -1;
      return Math.tan((a - 120) / 60 * Math.PI / 2) * 0.5
    },
    fi: function (a: number) {
      if (a == -1) return 180;
      return 120 + Math.atan(a / 0.5) * 60 / Math.PI * 2
    },
    g: m,
    orderRGB: function (a: number, b: number, c: number) {
      return new RGB(b, a, c)
    }
  },
  GGB: {
    a: COLOR_STAND.G,
    b: COLOR_STAND.GB,
    f: function (a: number) {
      if (a == 180) return -1;
      return Math.tan((210 - a) / 30 * Math.PI / 2) * 0.75
    },
    fi: function (a: number) {
      if (a == -1) return 180;
      return 210 - Math.atan(a / 0.75) * 30 / Math.PI * 2
    },
    g: g,
    orderRGB: function (a: number, b: number, c: number) {
      return new RGB(c, a, b)
    }
  },
  GBB: {
    a: COLOR_STAND.GB,
    b: COLOR_STAND.B,
    f: function (a: number) {
      if (a == 255) return -1;
      return Math.tan((a - 210) / 45 * Math.PI / 2) * 1.33
    },
    fi: function (a: number) {
      if (a == -1) return 255;
      return 210 + Math.atan(a / 1.33) * 45 / Math.PI * 2
    },
    g: m,
    orderRGB: function (a: number, b: number, c: number) {
      return new RGB(c, b, a)
    }
  },
  BBR: {
    a: COLOR_STAND.B,
    b: COLOR_STAND.BR,
    f: function (a: number) {
      if (a == 255) return -1;
      return Math.tan((315 - a) / 60 * Math.PI / 2) * 1.33
    },
    fi: function (a: number) {
      if (a == -1) return 255;
      return 315 - Math.atan(a / 1.33) * 60 / Math.PI * 2
    },
    g: g,
    orderRGB: function (a: number, b: number, c: number) {
      return new RGB(b, c, a)
    }
  },
  BRR: {
    a: COLOR_STAND.BR,
    b: COLOR_STAND.R,
    f: function (a: number) {
      if (a == 0) return -1;
      return Math.tan((a - 315) / 45 * Math.PI / 2) * 1.33
    },
    fi: function (a: number) {
      if (a == -1) return 0;
      return 315 + Math.atan(a / 1.33) * 45 / Math.PI * 2
    },
    g: m,
    orderRGB: function (a: number, b: number, c: number) {
      return new RGB(a, c, b)
    }
  },
  // deg为角度（0~360）
  getBaseColorByHue: function (deg: number) {
    var b, c, d, e;
    deg %= 360;
    e = this.getArc(deg);
    d = e.f(deg);
    c = e.g(e.a.HSV.V, e.b.HSV.V, d);
    b = e.g(e.a.HSV.S, e.b.HSV.S, d);
    return {
      HSV: new HSVColor(deg, b, c),
      RGB: this._getRGB(deg, b, c, e, d)
    }
  },
  // deg为角度
  getRGB: function (deg: number, b: number, c: number) {
    var d, e;
    d = this.getArc(deg);
    e = d.f(deg);
    return this._getRGB(deg, b, c, d, e)
  },
  _getRGB: function (a: any, b: number, c: number, d: ColorAxisFormat, e: number) {
    a = d.a.RGB;
    a = Math.max(a.R, Math.max(a.G, a.B));
    a *= c;
    b = a * (1 - b);
    return d.orderRGB(a, e == -1 ? b : (a + b * e) / (1 + e), b)
  },
  // getColorByRGB: function (a) {
  //   var b, c, d;
  //   a.R == a.B && a.R == a.G ? (c = b = 0, d = (a.R * 0.299 + a.G * 0.587 + a.B * 0.114) / 255) : (d = Math.max(a.R, Math.max(a.G, a.B)), c = Math.min(a.R, Math.min(a.G, a.B)), d == a.R ? c == a.B ? (b = a.G, a = this.RRG) : (b = a.B, a = this.BRR) : d == a.G ? c == a.R ? (b = a.B, a = this.GGB) : (b = a.R, a = this.RGG) : c == a.R ? (b = a.G, a = this.GBB) : (b = a.R, a = this.BBR), b = a.fi(b == c ? -1 : (d - b) / (b - c)), c = (d - c) / d, d /= 255);
  //   return new HSVColor(b, c, d)
  // }
}


// 渲染内容，函数，用于处理颜色
// varsOverlay 的值始终为[]空数组。
export class ColorAxis {
  H: number;
  Base: any;
  Col0: any;
  Col: Array<any>;

  constructor(h:number, S:number, V:number, contrastModel:any, varsOverlay:any, mode:number) {
    this.H = h;
    this.Base = ColorAnalysis.getBaseColorByHue(h);
    this.Col0 = this.getVariant(this.Base.HSV, S, V, mode);
    this.Col = [];
    if (varsOverlay[0]) {
      this.Col.push(this.getOverlayVariant(this.Base.HSV, varsOverlay[0][0], varsOverlay[0][1], mode))
    } else {
      this.Col.push(this.Col0)
    }
    let a = 0;
    for (let k = contrastModel.length; a < k; a++) {
      if (varsOverlay[a + 1]) {
        this.Col[a + 1] = this.getOverlayVariant(this.Base.HSV, varsOverlay[a + 1][0], varsOverlay[a + 1][1], mode)
      } else {
        this.Col[a + 1] = this.getVariant(this.Col0.HSV, contrastModel[a].dS, contrastModel[a].dV, mode)
      }
    }
  }

  getVariant (baseHsv:HSVColor, l:number, k:number, mode: number) {
    let hsv:any = {}
    hsv.h = baseHsv.H;
    hsv.s = l <= 0 ? baseHsv.S * (l + 1) : baseHsv.S + (1 - baseHsv.S) * l;
    hsv.v = k <= 0 ? baseHsv.V * (k + 1) : baseHsv.V + (1 - baseHsv.V) * k;

    // if (l)
    let a = new HSVColor(hsv.h, hsv.s, hsv.v);

    let rgb = ColorAnalysis.getRGB(a.H, a.S, a.V);
    mode == 1 ? rgb.toWebCol() : mode == 2 ? rgb.toPantone() : mode == 3 ? rgb.toRAL() : mode == 4 && rgb.toOpaltone();

    return {
      HSV: a,
      RGB: rgb
    }
  };

  getOverlayVariant (baseHsv:HSVColor, l:number, k:number, mode:number) {
    let a = new HSVColor(baseHsv.H, l, k);
    let rgb = ColorAnalysis.getRGB(a.H, a.S, a.V);
    mode == 1 ? rgb.toWebCol() : mode == 2 ? rgb.toPantone() : mode == 3 ? rgb.toRAL() : mode == 4 && rgb.toOpaltone();
    return {
      HSV: a,
      RGB: rgb
    }
  };
  getVarHSV (a:number) {
    return this.Col[a].HSV
  };
  getVarRGB (a:number) {
    return this.Col[a].RGB
  };

}





















interface ColorPlanFormat {
  title: string,
  colorList: Array<RGB>
}

export interface ColorSystemFormat {
  H: number,
  dS: number,
  dV: number,
  model: number,
  UIPlan: ColorPlanFormat,
  baseColor: ColorPlanFormat
}
